home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Book Chapters / 06 - Audio / Example Code / Hollywood API Test.c < prev    next >
Text File  |  1995-06-16  |  17KB  |  700 lines

  1. //----------------
  2. // Hollywood API for use with the Macintosh Sound Manager 3.0
  3. //
  4. // This code depends upon Universal Interfaces 2.0a3 or better from Apple Computer, Inc
  5. //
  6. // History
  7. //    1/8/95    Created by Steve Hales
  8. //    3/1/95    Music Architecture added by Jim Nitchals
  9. //----------------
  10. #include <Types.h>
  11. #include <Memory.h>
  12. #include <Quickdraw.h>
  13. #include <OSEvents.h>
  14. #include <Desk.h>
  15. #include <Events.h>
  16. #include <StandardFile.h>
  17. #include <Resources.h>
  18. #include <Windows.h>
  19. #include <Fonts.h>
  20. #include <TextEdit.h>
  21. #include <Menus.h>
  22. #include <Dialogs.h>
  23. #include <ToolUtils.h>
  24. #include <Sound.h>
  25. #include <AIFF.h>
  26.  
  27. // These includes are for the Apple Music Architecture
  28. #include <QuickTimeComponents.h>
  29. #include <Components.h>
  30.  
  31.  
  32. #define TRUE    true
  33. #define FALSE    false
  34.  
  35. #include "Hollywood.h"
  36.  
  37. // Defines and Structures
  38. #define rAboutDialog            128
  39.  
  40. // Menu defines
  41. #define kMaxMenus            2
  42.  
  43. #define rAppleMenu            1
  44. #define    kAbout            1
  45.  
  46. #define rFileMenu            2
  47. #define    kPlayFile            1
  48. #define    kPlaySnd1            2
  49. #define    kPlaySnd2            3
  50. #define    kPlaySnd3            4
  51. #define    kPlaySnd4            5
  52. #define    kDoStereoPan        6
  53. #define    kSaveAIFF            7
  54. #define    kPlayMusicNotes    9
  55. #define    kPlayQuickTime        10
  56. #define    kQuitApp            12
  57.  
  58. #define kStereoPanCount        30        // the amount of change during a stereo pan
  59. #define kStereoDelay        4L        // amount of ticks to pass before changing the stereo position
  60. #define kPanVoice            1        // which voice to work with durning the pan test
  61.  
  62. // Examples
  63. #define rExampleSound1        128        // snd examples
  64. #define rExampleSound2        129
  65.  
  66. #define rExampleRaw1        128        // raw waveform examples
  67. #define rExampleRaw2        129
  68.  
  69. // Variables
  70. static Boolean        appDoneFlag;
  71. static Boolean        movieInProgress;
  72. static WindowPtr    theMovieDisplayWindow = NULL;
  73. static Movie        theMovie;
  74.  
  75. static char        theDate[] = __DATE__;
  76. static char        theTime[] = __TIME__;
  77.  
  78. static MenuHandle    Menu[kMaxMenus];
  79.  
  80. static Boolean        processStereoPan;
  81. static short int        stereoPos, stereoDirection;
  82. static long            lastProcessTick;
  83.  
  84. // Functions
  85. static void StartQuickTimeMovie(void);
  86. static void ProcessQuickTimeMovie(void);
  87. static void EndQuickTimeMovie(void);
  88.  
  89.  
  90. static Boolean GetReadFileName(char *pName, short *pVRef, OSType *pType, short typeCount)
  91. {
  92.     static Point anchor = {100, 7};    /* top-left */
  93.     SFReply reply;
  94.  
  95.     SFGetFile(anchor, NULL, NULL, typeCount, pType, NULL, &reply);
  96.  
  97.     if (pType)
  98.     {
  99.         pType[0] = reply.fType;
  100.     }
  101.     BlockMove((void *)reply.fName, pName, 63L);
  102.     *pVRef = reply.vRefNum;
  103.     return(reply.good);
  104. }
  105.  
  106. static Boolean GetWriteFileName(void *pName, short int *pVRef, void *pSaveText)
  107. {
  108.     static Point anchor = {50, 105};    /* top-left */
  109.     SFReply reply;
  110.  
  111.     SFPutFile(anchor, (ConstStr255Param)pSaveText, (ConstStr255Param)pName, NULL, &reply);
  112.     if (reply.good == FALSE)
  113.     {
  114.         return(FALSE);    /* user pressed CANCEL */
  115.     }
  116.     
  117.     *pVRef = reply.vRefNum;
  118.     BlockMove(reply.fName, pName, 63L);
  119.     return(TRUE);
  120. }
  121.  
  122. static void DisplayAboutBox(void)
  123. {
  124.     DialogRecord        dRecord;
  125.     GrafPtr            savePort;
  126.     register DialogPtr    theDialog;
  127.     short            theItem;
  128.  
  129.     GetPort(&savePort);
  130.     theDialog = GetNewDialog(rAboutDialog, &dRecord, (WindowPtr)-1L);
  131.     SetPort(theDialog);
  132.     ModalDialog(NULL, &theItem);
  133.     CloseDialog(theDialog);    // I supplied memory for GetNewDialog
  134.  
  135.     SetPort(savePort);
  136. }
  137.  
  138. static void StartQuickTimeMovie(void)
  139. {
  140.     SFTypeList        theTypeList;
  141.     StandardFileReply    theReply;
  142.     short int             myRef;
  143.     Rect                wRect;
  144.     FSSpec            theMidiFile;
  145.     OSErr            theErr;
  146.  
  147.     if (movieInProgress)
  148.     {
  149.         EndQuickTimeMovie();
  150.         movieInProgress = FALSE;
  151.     }
  152.     /* Let the user select a movie */
  153.     theTypeList[0] = MovieFileType;
  154.     theTypeList[1] = 'Midi';
  155.     StandardGetFile(NULL, 2, theTypeList, &theReply);
  156.     if (theReply.sfGood)
  157.     {
  158.         /* initialize movie toolbox */
  159.         theErr = EnterMovies();
  160.         if (theErr == noErr)
  161.         {
  162.             if (theReply.sfType == 'Midi')
  163.             {    // Then we are converting a Midi file into a QuickTime movie
  164.                 theMidiFile = theReply.sfFile;
  165.                 StandardPutFile(NULL, theReply.sfFile.name, &theReply);
  166.                 if (theReply.sfGood)
  167.                 {
  168.                     theErr = ConvertFileToMovieFile(&theMidiFile, &theReply.sfFile, 'TVOD', 0, 
  169.                                                 NULL, showUserSettingsDialog, 0L, NULL, 0L);
  170.                 }
  171.                 else
  172.                 {
  173.                     theErr = badFormat;
  174.                 }
  175.             }
  176.             /* open the movie file, get the movie from it, then close it */
  177.             if ( (theErr == noErr) && (OpenMovieFile(&theReply.sfFile, &myRef, fsRdPerm) == noErr) )
  178.             {
  179.                 if (NewMovieFromFile(&theMovie, myRef, NULL, NULL, newMovieActive, NULL) == noErr)
  180.                 {
  181.                     /* Find out the size of the movie. */
  182.                     GetMovieBox (theMovie, &wRect);
  183.                     
  184.                     /* If the movie has no video, don't display any window. */
  185.                     if (wRect.bottom)
  186.                     {
  187.                         wRect.top += 48;
  188.                         wRect.left += 48;
  189.                         wRect.bottom += 48;
  190.                         wRect.right += 48;
  191.                         theMovieDisplayWindow = NewCWindow (NULL, &wRect, "\pMovie Window", TRUE, plainDBox,
  192.                                         (WindowPtr) -1L, TRUE, 0);
  193.                         SetMovieGWorld (theMovie, (CGrafPtr) theMovieDisplayWindow, 0);
  194.                     }
  195.                 
  196.                     /* Tell QuickTime we're playing from the beginning. */
  197.                     GoToBeginningOfMovie(theMovie);
  198.                     
  199.                     /* PrerollMovie helps QuickTime pre-load parts of the movie to
  200.                        give smoother playback.
  201.                 
  202.                        Second parameter is the time we expect to start playing at.
  203.                        Third parameter is the playback rate we expect to be using.
  204.                        1.0 in fixed rate. */
  205.                     PrerollMovie(theMovie, 0, 0x10000);
  206.                     
  207.                     /* Start playing forward. */
  208.                     StartMovie(theMovie);
  209.                     movieInProgress = TRUE;
  210.                 }
  211.                 CloseMovieFile(myRef);
  212.             }
  213.         }
  214.     }
  215. }
  216.  
  217. static void ProcessQuickTimeMovie(void)
  218. {
  219.     if (movieInProgress)
  220.     {
  221.         if (IsMovieDone(theMovie))
  222.         {
  223.             EndQuickTimeMovie();
  224.         }
  225.         else
  226.         {
  227.             /* Your event loop should call MoviesTask very regularly for smooth playback.
  228.                The second parameter to MoviesTask is the maximum number of milliseconds
  229.                QuickTime may use when playing multiple movies.  Pass 0 to allow QuickTime
  230.                to service every movie properly. */
  231.             MoviesTask(theMovie, 0);
  232.         }
  233.     }
  234. }
  235.  
  236. static void EndQuickTimeMovie(void)
  237. {
  238.     if (movieInProgress)
  239.     {
  240.         /* Throw away the window if there was one. */
  241.         if (theMovieDisplayWindow)
  242.         {
  243.             DisposeWindow(theMovieDisplayWindow);
  244.             theMovieDisplayWindow = NULL;
  245.         }
  246.         /* Make this call to free up resources used by QuickTime and the movie. */
  247.         DisposeMovie(theMovie);
  248.         movieInProgress = FALSE;
  249.         ExitMovies();
  250.     }
  251. }
  252.  
  253.  
  254.  
  255. static void PlayQuickTimeNotes(void)
  256. {
  257.     NoteAllocator theNoteAllocator;    /* The music note allocator component */
  258.     NoteChannel myNoteChannel;        /* A channel to play notes through */
  259.     NoteRequest myNoteRequest;        /* A structure describing the instrument we want to play */
  260.     short int i, velocity, instrument_index;
  261.     unsigned long current_tick_count;
  262.     /* This is a list of General MIDI instrument numbers we want to play. */
  263.     static int instrument_list[6] = {1, 5, 7, 8, 12, 13};
  264.  
  265.     /* Open the note allocator component */
  266.     theNoteAllocator = OpenDefaultComponent(kNoteAllocatorType, 0);
  267.  
  268.     /* Walk through our list of available instruments. */
  269.     for (instrument_index = 0; instrument_index < 6; instrument_index++)
  270.     {
  271.         /* Set up a NoteRequest structure with a request for a piano with polyphony of 1. */
  272.         myNoteRequest.polyphony = 1;
  273.         myNoteRequest.typicalPolyphony = 1<<16;
  274.     
  275.         /* We can request a specific instrument by name.  If it's not found, the gmNumber field
  276.            provides the General MIDI fallback instrument. */
  277.         myNoteRequest.tone.synthesizerType = 0;
  278.         myNoteRequest.tone.synthesizerName[0] = 0;
  279.         myNoteRequest.tone.instrumentName[0] = 0;
  280.         myNoteRequest.tone.instrumentNumber = 0;
  281.         myNoteRequest.tone.gmNumber = instrument_list[instrument_index];
  282.     
  283.         /* Allocate a note channel with our desired instrument as filled out in the NoteRequest */
  284.         NANewNoteChannel(theNoteAllocator, &myNoteRequest, &myNoteChannel);
  285.         
  286.         /* Load the resources needed by the instrument */
  287.         NAPrerollNoteChannel(theNoteAllocator, myNoteChannel);
  288.     
  289.         /* Perform a loop, playing notes at increasing pitch and velocity, using TickCount()
  290.            as a timebase.  You can play notes at interrupt time, so you can schedule note
  291.            events with the Time Manager, or through your own schemes. */
  292.         current_tick_count = TickCount() + 6;
  293.         for (i = 32; i < 90 && Button() == false; i += 3)
  294.         {
  295.             velocity = i + 10;
  296.             /* Play the Note */
  297.             NAPlayNote(theNoteAllocator, myNoteChannel, i, velocity);
  298.             
  299.             /* Wait awhile */
  300.             while (current_tick_count > TickCount()) {};
  301.             current_tick_count += 6;    /* Prepare to do this again in another 1/10th-second. */
  302.             
  303.             /* Stop playing the note. */
  304.             NAPlayNote(theNoteAllocator, myNoteChannel, i, 0);
  305.         }
  306.  
  307.         /* Wait for the last note to decay away to silence. */
  308.         current_tick_count += 20;
  309.         while (current_tick_count > TickCount()) {};
  310.     
  311.         /* Dispose the note channel when we're done with it. */
  312.         NADisposeNoteChannel(theNoteAllocator, myNoteChannel);
  313.     }
  314.     CloseComponent(theNoteAllocator);
  315. }
  316.  
  317.  
  318.  
  319. static void FilePlayCallback(short int voiceNumber, short int what, long userData)
  320. {
  321.  
  322. }
  323.  
  324. static void PlayFile(void)
  325. {
  326.     OSType    types[2];
  327.     FSSpec    theFile;
  328.     OSErr    theErr;
  329.  
  330.     types[0] = AIFFID;        // from AIFF.h
  331.     types[1] = AIFCID;        // from AIFF.h
  332.  
  333.     if (GetReadFileName((char *)theFile.name, &theFile.vRefNum, types, 2))
  334.     {
  335.         theFile.parID = 0;
  336.         theErr = HY_StartFilePlay(kPanVoice, &theFile, FilePlayCallback, 0, 40000L, TRUE);
  337.     }
  338. }
  339.  
  340.  
  341. static void PlaySoundEffect1(void)
  342. {
  343.     static SndReference    theSound1 = NULL;
  344.  
  345.     if (theSound1 == NULL)        // only load this sample in once
  346.     {
  347.         theSound1 = HY_GetSoundResource(rExampleSound1);
  348.     }
  349.     if (theSound1)
  350.     {
  351.         HY_PlaySoundHandle(0, theSound1, NULL, 0, TRUE);
  352.     }
  353. }
  354.  
  355. static void PlaySoundEffect2(void)
  356. {
  357.     static SndReference    theSound2 = NULL;
  358.  
  359.     if (theSound2 == NULL)        // only load this sample in once
  360.     {
  361.         theSound2 = HY_GetSoundResource(rExampleSound2);
  362.     }
  363.     if (theSound2)
  364.     {
  365.         HY_PlaySoundHandle(kPanVoice, theSound2, NULL, 0, TRUE);
  366.     }
  367. }
  368.  
  369. static void PlaySoundEffect3(void)
  370. {
  371.     Handle    theSample, theNewSample;
  372.     Handle    theCompressedSample;
  373.  
  374.     theSample = GetResource('wave', rExampleRaw1);
  375.     if (theSample)
  376.     {
  377.         HLock(theSample);
  378.         // our raw waveform is mono 8 bit, and should be played back at 11 kHz.
  379.         theNewSample = HY_CreateSndResourceFromPtr(*theSample, GetHandleSize(theSample), rate11khz,
  380.                                                 8, 1, kMiddleC);
  381.         HUnlock(theSample);
  382.  
  383.         if (theNewSample)
  384.         {
  385.             HY_RegisterThisSound(theNewSample);
  386.             HY_PlaySoundHandle(0, theNewSample, NULL, 0L, TRUE);
  387.             while (HY_IsVoiceEmpty(0) == FALSE)
  388.             {
  389.                 HY_ServiceTasks();        // at least call once in a while
  390.             }
  391.             HY_UnregisterSoundResource(theNewSample);
  392.             DisposeHandle(theNewSample);
  393.         }
  394.  
  395.         // now MACE compress it, and play it back.
  396.         HLock(theSample);
  397.         // 6 to 1 compression is pretty bad in this case, but 3 to 1 is ok
  398.         theCompressedSample = HY_CreateMACESndResourceFromPtr(sixToOne, *theSample, GetHandleSize(theSample), 
  399.                                         rate11khz, 8, 1, kMiddleC);
  400.         HUnlock(theSample);
  401.         ReleaseResource(theSample);
  402.  
  403.         if (theCompressedSample)
  404.         {
  405.             HY_RegisterThisSound(theCompressedSample);
  406.             HY_PlaySoundHandle(0, theCompressedSample, NULL, 0L, TRUE);
  407.             while (HY_IsVoiceEmpty(0) == FALSE)
  408.             {
  409.                 HY_ServiceTasks();        // at least call once in a while
  410.             }
  411.             HY_UnregisterSoundResource(theCompressedSample);
  412.             DisposeHandle(theCompressedSample);
  413.         }
  414.     }
  415. }
  416.  
  417. static void PlaySoundEffect4(void)
  418. {
  419.     Handle    theSample;
  420.     Handle    theNewSample;
  421.  
  422.     theSample = GetResource('wave', rExampleRaw2);
  423.     if (theSample)
  424.     {
  425.         HLock(theSample);
  426.         // our raw waveform is stereo 8 bit, and should be played back at 14321 kHz.
  427.         theNewSample = HY_CreateSndResourceFromPtr(*theSample, GetHandleSize(theSample), X2Fix(20000.0),
  428.                                                 8, 2, 60);
  429.         HUnlock(theSample);
  430.         ReleaseResource(theSample);
  431.  
  432.         if (theNewSample)
  433.         {
  434.             HY_RegisterThisSound(theNewSample);
  435.             HY_PlaySoundHandle(0, theNewSample, NULL, 0L, TRUE);
  436.             while (HY_IsVoiceEmpty(0) == FALSE)
  437.             {
  438.                 HY_ServiceTasks();        // at least call once in a while
  439.             }
  440.             HY_UnregisterSoundResource(theNewSample);
  441.             DisposeHandle(theNewSample);
  442.         }
  443.     }
  444. }
  445.  
  446. static void PhaseWaveform(register char *p, register long size)
  447. {
  448.     register char *ep;
  449.  
  450.     ep = p + size;
  451.     while (p < ep)
  452.     {
  453.         *p -= 0x80;
  454.         p++;
  455.     }
  456. }
  457.  
  458. static void SaveAIFFFile(void)
  459. {
  460.     Handle        theSample;
  461.     FSSpec        theFile;
  462.     OSErr        theErr;
  463.     long            length;
  464.  
  465.     theFile.name[0] = 0;
  466.     if (GetWriteFileName(theFile.name, &theFile.vRefNum, "\pSave Example AIFF…"))
  467.     {
  468.         theFile.parID = 0;
  469.         theSample = GetResource('wave', rExampleRaw1);
  470.         if (theSample)
  471.         {
  472.             DetachResource(theSample);
  473.             HLock(theSample);
  474.             length = GetHandleSize(theSample);
  475.  
  476.     // AIFF files expect the volume levels to be in the range of -128 to 127 for 8 bit data, and 
  477.     // -32768 to 32767. Where zero is silence. The standard Macintosh 8 bit resource silence is 128,
  478.     // so we have to phase the sample back.
  479.  
  480.             PhaseWaveform(*theSample, length);
  481.  
  482.             theErr = HY_CreateAIFFFileFromPtr(&theFile, *theSample, length, 
  483.                                         rate11khz, 
  484.                                         8, 1);
  485.             HUnlock(theSample);
  486.             DisposeHandle(theSample);
  487.         }
  488.     }
  489. }
  490.  
  491. static void ProcessStereoPan(short int voiceNumber)
  492. {
  493.     if (TickCount() > lastProcessTick)
  494.     {
  495.         lastProcessTick = TickCount() + kStereoDelay;
  496.  
  497.         HY_SetStereoPosition(voiceNumber, stereoPos);
  498.         stereoPos += stereoDirection;
  499.         if (stereoPos < kFullLeft)
  500.         {
  501.             stereoDirection = kStereoPanCount;
  502.             stereoPos += stereoDirection;
  503.         }
  504.         if (stereoPos > kFullRight)
  505.         {
  506.             stereoDirection = -kStereoPanCount;
  507.             stereoPos += stereoDirection;
  508.         }
  509.     }
  510. }
  511.  
  512. static void ProcessMenuCommands(long menuSelection)
  513. {
  514.     short int    theMenuSelection, theItemSelection;
  515.     Str255    deskName;
  516.     GrafPtr     savePort;
  517.  
  518.     theMenuSelection = HiWord(menuSelection);
  519.     theItemSelection = LoWord(menuSelection);
  520.     
  521.     switch (theMenuSelection) 
  522.     {
  523.         case rAppleMenu:
  524.             switch (theItemSelection)
  525.             {
  526.                 case kAbout:
  527.                     DisplayAboutBox();
  528.                     break;
  529.                 default:
  530.                     GetItem(Menu[0], theItemSelection, deskName);
  531.                     GetPort(&savePort);
  532.                     OpenDeskAcc(deskName);
  533.                     SetPort(savePort);
  534.                     break;
  535.             }
  536.             break;
  537.         case rFileMenu:
  538.             switch (theItemSelection)
  539.             {
  540.                 case kPlayFile:
  541.                     PlayFile();
  542.                     break;
  543.                 case kPlaySnd1:
  544.                     PlaySoundEffect1();
  545.                     break;
  546.                 case kPlaySnd2:
  547.                     PlaySoundEffect2();
  548.                     break;
  549.                 case kPlaySnd3:
  550.                     PlaySoundEffect3();
  551.                     break;
  552.                 case kPlaySnd4:
  553.                     PlaySoundEffect4();
  554.                     break;
  555.                 case kDoStereoPan:
  556.                     processStereoPan = TRUE;
  557.                     stereoPos = kMiddle;
  558.                     HY_SetStereoPosition(kPanVoice, stereoPos);
  559.                     stereoDirection = -kStereoPanCount;    // start left
  560.                     lastProcessTick = TickCount() + kStereoDelay;
  561.                     break;
  562.                 case kSaveAIFF:
  563.                     SaveAIFFFile();
  564.                     break;
  565.                 case kPlayMusicNotes:
  566.                     PlayQuickTimeNotes();
  567.                     break;
  568.                 case kPlayQuickTime:
  569.                     StartQuickTimeMovie();
  570.                     break;
  571.                 case kQuitApp:
  572.                     appDoneFlag = TRUE;
  573.                     break;
  574.             }
  575.             break;
  576.     }
  577.     HiliteMenu(0);
  578. }
  579.  
  580.  
  581. void main()
  582. {
  583.     EventRecord    theEvents;
  584.     WindowPtr    theWindow;
  585.     OSErr        theErr;
  586.     short int        count;
  587.  
  588. // NOTE:  The order of initilizing the system seems very important when running under
  589. //        MultFinder!!!
  590. #if THINK_C
  591.     InitGraf(&thePort);            // set up screen port
  592. #else
  593.     InitGraf(&qd.thePort);
  594. #endif
  595.     InitFonts();                // set up font manager
  596.     InitWindows();                // set up window stuff
  597.     InitMenus();                // set up menu mgr
  598.     TEInit();                    // set up text editor for system use
  599.     InitDialogs(NULL);            // set up Dialog stuff
  600.     InitCursor();                // put pointer shape in mouse
  601.  
  602.     MaxApplZone();                // force expansion
  603.     FlushEvents(everyEvent, 0);    // clear all events
  604.     MoreMasters();
  605.     MoreMasters();
  606.  
  607.     // Setup menus
  608.     Menu[0] = GetMenu(rAppleMenu);
  609.     AddResMenu(Menu[0], 'DRVR');
  610.     Menu[1] = GetMenu(rFileMenu);
  611.  
  612.     for (count = 0; count < kMaxMenus; count++)
  613.     {
  614.         if (Menu[count])
  615.         {
  616.             InsertMenu(Menu[count], 0);
  617.         }
  618.     }
  619.     DrawMenuBar();
  620.  
  621.     theErr = HY_Setup(kUseStereo, 3);
  622.     appDoneFlag = FALSE;
  623.     processStereoPan = FALSE;
  624.     movieInProgress = FALSE;
  625.     while (appDoneFlag == FALSE)
  626.     {
  627.         HY_ServiceTasks();
  628.  
  629.         ProcessQuickTimeMovie();
  630.         if (processStereoPan)
  631.         {
  632.             ProcessStereoPan(kPanVoice);
  633.         }
  634.         if (WaitNextEvent(everyEvent,  &theEvents, 0L, NULL))
  635.         {
  636.             switch(theEvents.what)
  637.             {
  638.                 case mouseDown:
  639.                     switch (FindWindow(theEvents.where, &theWindow)) 
  640.                     {
  641.                         case inSysWindow:
  642.                             SystemClick(&theEvents, theWindow);
  643.                             break;
  644.                         case inMenuBar:
  645.                             ProcessMenuCommands(MenuSelect(theEvents.where));
  646.                             break;
  647.                     }
  648.                     break;
  649.                 case app4Evt:        // Suspend/Resume Events
  650.                     if ( ((theEvents.message >> 24L) & 0x00FF) == 0x01)
  651.                     {
  652.                         if (theEvents.message & 1)    // message field contains flags
  653.                         {
  654.                         //    HY_ResumeHardware();
  655.                         }
  656.                         else
  657.                         {
  658.                             // suspend
  659.                         //    HY_PauseHardware();
  660.                         }
  661.                     }
  662.                     break;
  663.                 case autoKey:
  664.                 case keyDown:
  665.                     count = theEvents.message & 0xFF;
  666.                     if (theEvents.modifiers & cmdKey)
  667.                     {
  668.                         ProcessMenuCommands(MenuKey(count));
  669.                     }
  670.                     else
  671.                     {
  672.                         switch(count)
  673.                         {
  674.                             case 'q':
  675.                                 appDoneFlag = TRUE;
  676.                                 break;
  677.                         }
  678.                     }
  679.                     break;
  680.             }
  681.         }
  682.     }
  683.     // release menus
  684.     for (count = 0; count < kMaxMenus; count++)
  685.     {
  686.         if (Menu[count])
  687.         {
  688.             ReleaseResource((Handle)Menu[count]);
  689.         }
  690.     }
  691.     HY_UnregisterAllSoundResources();
  692.     HY_Cleanup();
  693.     EndQuickTimeMovie();
  694.     FlushEvents(everyEvent, 0);    // clear all events
  695. }
  696.  
  697. // EOF of Hollywood API Test.c
  698.  
  699.  
  700.